package com.wh.minihelp.filter.impl;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.wh.db.jdbc.mysql.BaseJDBCDao;
import com.wh.lang.LogUtil;
import com.wh.lang.LogicException;
import com.wh.minihelp.filter.IFunctionContext;
import com.wh.minihelp.filter.IFunctionService;
import com.wh.minihelp.flower.service.FlowerService;
import com.wh.minihelp.user.service.UserService;
import com.wh.minihelp.weixin.service.WeixinService;

/**
 * WEB端，生产环境下的上下文环境
 * 
 * @author washheart@163.com
 */
public abstract class FunctionContext implements IFunctionContext {
	static final String DRIVER = "com.mysql.jdbc.Driver";
	private final static Map<String, Class<? extends IFunctionService>> ServiceClasses = new HashMap<String, Class<? extends IFunctionService>>();

	static {
		ServiceClasses.put(WeixinService.Module, WeixinService.class);
		ServiceClasses.put(UserService.Module, UserService.class);
		ServiceClasses.put(FlowerService.Module, FlowerService.class);
	}
	private HttpSession session;
	private HttpServletRequest req;
	private HttpServletResponse rep;
	private ServletContext ctx;
	private Connection cnn;
	private Map<String, BaseJDBCDao> daos = new HashMap<String, BaseJDBCDao>();
	private Map<String, IFunctionService> services = new HashMap<String, IFunctionService>();

	public FunctionContext() {}

	public void initContext(ServletContext ctx, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
		this.ctx = ctx;
		this.session = session;
		this.req = request;
		this.rep = response;
	}

	@Override
	public void forwardModule(String module, String method) throws ServletException, IOException {
		if (module.startsWith("/")) module = module.substring(1);
		IFunctionService service = services.get(module);
		if (service == null) {
			service = createService(module);
			services.put(module, service);
		}
		if (service != null) {
			service.dispather(this, method);
		} else {
			this.message("请用微信扫码访问小小助手~<br><img src='" + req.getContextPath() + "/res/img/wx.jpg'>");
		}
	}

	private IFunctionService createService(String module) {
		Class<? extends IFunctionService> clazz = ServiceClasses.get(module);
		if (clazz == null) return null;
		try {
			return clazz.newInstance();
		} catch (Throwable e) {
			if (LogUtil.rootLog.isErrorEnabled()) LogUtil.rootLog.error("创建【" + module + "】服务失败。", e);
		}
		return null;
	}

	@Override
	public void forward(String url) {
		try {
			ctx.getRequestDispatcher(url).forward(req, rep);
		} catch (Throwable e) {
			LogUtil.rootLog.error("跳转页面出错(forward)。", e);
		}
	}

	@Override
	public void sendRedirect(String url) {
		try {
			rep.sendRedirect(url);
		} catch (Throwable e) {
			LogUtil.rootLog.error("跳转页面出错(Redirect)。", e);
		}

	}

	@Override
	public void json(String s) throws IOException {
		rep.setCharacterEncoding("UTF-8");
		rep.setContentType("text/html;charset=UTF-8");
		PrintWriter out = rep.getWriter();
		out.write(s);
		out.flush();
		out.close();
	}

	@Override
	public void message(String str) throws IOException {
		rep.setCharacterEncoding("UTF-8");
		rep.setContentType("text/html;charset=UTF-8");
		PrintWriter out = rep.getWriter();
		out.write(str);
		out.flush();
		out.close();
	}

	@Override
	public void xml(String xml) throws IOException {
		rep.setCharacterEncoding("UTF-8");
		rep.setContentType("application/xml;charset=UTF-8");
		PrintWriter out = rep.getWriter();
		out.write(xml);
		out.flush();
		out.close();
	}

	@Override
	public void error(String msg) throws ServletException, IOException {
		req.setAttribute("error", msg);
		ctx.getRequestDispatcher("/WEB-INF/common/error.jsp").forward(req, rep);//
	}

	@Override
	public String getParameter(String name) {
		return req.getParameter(name);
	}

	// 获取数据数据库连接
	public Connection getConnection() {
		if (cnn == null) {
			try {
				cnn = createConnection();
			} catch (Throwable e) {
				LogUtil.rootLog.error("连接数据库出错。", e);
			}
		}
		return cnn;
	}

	@Override
	public void clear() {
		if (cnn != null) {
			try {
				try {
					cnn.commit();
				} catch (SQLException ex) {
					// String err = "同步数据库出错。DBURL=" + name;
					try {
						cnn.rollback();
					} catch (Exception e) {} // end try
					throw ex;
				}
				cnn.close();
			} catch (Throwable e) {
				LogUtil.rootLog.error("关闭数据库出错。", e);
			}
		}
	}

	@Override
	public Object getSessionAttribute(String key) {
		return this.session.getAttribute(key);
	}

	@Override
	public void setSessionAttribute(String key, Object value) {
		this.session.setAttribute(key, value);
	}

	@Override
	public Object getRequestAttribute(String key) {
		return this.req.getAttribute(key);
	}

	@Override
	public void setRequestAttribute(String key, Object value) {
		this.req.setAttribute(key, value);
	}

	@Override
	public InputStream getRequestInputStream() throws IOException {
		return this.req.getInputStream();
	}

	@Override
	public String getRequestCharacterEncoding() {
		return this.req.getCharacterEncoding();
	}

	@Override
	public HttpServletRequest getRequest() {
		return this.req;
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T extends BaseJDBCDao> T getDao(Class<T> clazz) {
		String key = clazz.getName();
		T dao = (T) this.daos.get(key);
		if (dao == null) {
			try {
				dao = clazz.newInstance();
			} catch (Throwable e) {
				throw new LogicException("无法创建访问数据库的dao", e);
			}
			dao.initBy(this);
			this.daos.put(key, dao);
		}
		return dao;
	}
}